//! $Id: ProviderContext.h 27 2011-09-16 13:28:08Z skagget77 $
//!
//! @file    ProviderContext.h
//! @author  Johan Andersson <skagget77@gmail.com>
//! @date    Sat Oct 10 19:15 2009
//! @ingroup IoCpp
//!

#if !defined(IOCPP_CONFIG_PROVIDERCONTEXT_H)
#define IOCPP_CONFIG_PROVIDERCONTEXT_H

#include "IoCpp/Config/BindContext.h"
#include "IoCpp/Config/NameContext.h"
#include "IoCpp/Config/NameSingletonContext.h"

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>

namespace IoCpp
{
   //!
   //! Proxy to represent a constant value as a provider.
   //!
   //! @param  constant The constant value.
   //!
   //! @return The constant value.
   //!
   template<class T1>
   T1 ConstantProxy( T1 constant ) {
      return constant;
   }

   //!
   //! @author  Johan Andersson <skagget77@gmail.com>
   //! @date    Sat Oct 10 19:15 2009
   //! @ingroup IoCpp
   //!
   //! The ProviderContext class, part of the fluent interface used when
   //! binding a type to a provider. Specifies the provider being bound.
   //!
   template<class T1>
   class ProviderContext
   {
   public :
      //!
      //! Creates a new instance of the ProviderContext class.
      //!
      //! @param context The BindContext holding the state of the fluent
      //!                interface while binding a type to a provider.
      //!
      ProviderContext( boost::shared_ptr<BindContext<T1> > context )
         : mContext(context) {
      }

      //!
      //! Binds the constant value.
      //!
      //! @param constant The constant value.
      //!
      NameContext<T1> ToConstant( T1 constant ) 
      {
         mContext->SetProvider(boost::bind(ConstantProxy<T1>, constant));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2>
      NameContext<T1> ToProvider( T2 (*provider)() )
      {
         mContext->SetProvider(provider);

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3>
      NameContext<T1> ToProvider( T2 (*provider)(T3) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4>
      NameContext<T1> ToProvider( T2 (*provider)(T3, T4))
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5>
      NameContext<T1> ToProvider( T2 (*provider)(T3, T4, T5))
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6>
      NameContext<T1> ToProvider( T2 (*provider)(T3, T4, T5, T6) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6, class T7>
      NameContext<T1> ToProvider( T2 (*provider)(T3, T4, T5, T6, T7) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container),
            boost::bind(&IContainer::Inject<T7>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2>
      NameSingletonContext<T1> ToProvider( T2* (*provider)() )
      {
         mContext->SetProvider(provider);

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3>
      NameSingletonContext<T1> ToProvider( T2* (*provider)(T3) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4>
      NameSingletonContext<T1> ToProvider( T2* (*provider)(T3, T4))
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5>
      NameSingletonContext<T1> ToProvider( T2* (*provider)(T3, T4, T5))
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6>
      NameSingletonContext<T1> ToProvider( T2* (*provider)(T3, T4, T5, T6) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6, class T7>
      NameSingletonContext<T1> ToProvider( T2* (*provider)(T3, T4, T5, T6, T7) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container),
            boost::bind(&IContainer::Inject<T7>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2>
      NameSingletonContext<T1> ToProvider( boost::shared_ptr<T2> (*provider)() )
      {
         mContext->SetProvider(provider);

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3>
      NameSingletonContext<T1> ToProvider( boost::shared_ptr<T2> (*provider)(T3) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4>
      NameSingletonContext<T1> ToProvider( boost::shared_ptr<T2> (*provider)(T3, T4))
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5>
      NameSingletonContext<T1> ToProvider( boost::shared_ptr<T2> (*provider)(T3, T4, T5))
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6>
      NameSingletonContext<T1> ToProvider( boost::shared_ptr<T2> (*provider)(T3, T4, T5, T6) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6, class T7>
      NameSingletonContext<T1> ToProvider( boost::shared_ptr<T2> (*provider)(T3, T4, T5, T6, T7) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container),
            boost::bind(&IContainer::Inject<T7>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2>
      NameContext<T1> ToProvider( T2 (*provider)(IContainerPtr) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3>
      NameContext<T1> ToProvider( T2 (*provider)(IContainerPtr, T3) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4>
      NameContext<T1> ToProvider( T2 (*provider)(IContainerPtr, T3, T4))
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5>
      NameContext<T1> ToProvider( T2 (*provider)(IContainerPtr, T3, T4, T5))
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6>
      NameContext<T1> ToProvider( T2 (*provider)(IContainerPtr, T3, T4, T5, T6) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6, class T7>
      NameContext<T1> ToProvider( T2 (*provider)(IContainerPtr, T3, T4, T5, T6, T7) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container),
            boost::bind(&IContainer::Inject<T7>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2>
      NameSingletonContext<T1> ToProvider( T2* (*provider)(IContainerPtr) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3>
      NameSingletonContext<T1> ToProvider( T2* (*provider)(IContainerPtr, T3) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4>
      NameSingletonContext<T1> ToProvider( T2* (*provider)(IContainerPtr, T3, T4))
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5>
      NameSingletonContext<T1> ToProvider( T2* (*provider)(IContainerPtr, T3, T4, T5))
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6>
      NameSingletonContext<T1> ToProvider( T2* (*provider)(IContainerPtr, T3, T4, T5, T6) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6, class T7>
      NameSingletonContext<T1> ToProvider( T2* (*provider)(IContainerPtr, T3, T4, T5, T6, T7) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container),
            boost::bind(&IContainer::Inject<T7>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2>
      NameSingletonContext<T1> ToProvider( boost::shared_ptr<T2> (*provider)(IContainerPtr) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3>
      NameSingletonContext<T1> ToProvider( boost::shared_ptr<T2> (*provider)(IContainerPtr, T3) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4>
      NameSingletonContext<T1> ToProvider( boost::shared_ptr<T2> (*provider)(IContainerPtr, T3, T4))
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5>
      NameSingletonContext<T1> ToProvider( boost::shared_ptr<T2> (*provider)(IContainerPtr, T3, T4, T5))
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6>
      NameSingletonContext<T1> ToProvider( boost::shared_ptr<T2> (*provider)(IContainerPtr, T3, T4, T5, T6) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6, class T7>
      NameSingletonContext<T1> ToProvider( boost::shared_ptr<T2> (*provider)(IContainerPtr, T3, T4, T5, T6, T7) )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container),
            boost::bind(&IContainer::Inject<T7>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2>
      NameContext<T1> ToProvider( boost::function<T2 ()> provider )
      {
         mContext->SetProvider(provider);

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3>
      NameContext<T1> ToProvider( boost::function<T2 (T3)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4>
      NameContext<T1> ToProvider( boost::function<T2 (T3, T4)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5>
      NameContext<T1> ToProvider( boost::function<T2 (T3, T4, T5)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6>
      NameContext<T1> ToProvider( boost::function<T2 (T3, T4, T5, T6)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6, class T7>
      NameContext<T1> ToProvider( boost::function<T2 (T3, T4, T5, T6, T7)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container),
            boost::bind(&IContainer::Inject<T7>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2>
      NameSingletonContext<T1> ToProvider( boost::function<T2* ()> provider )
      {
         mContext->SetProvider(provider);

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3>
      NameSingletonContext<T1> ToProvider( boost::function<T2* (T3)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4>
      NameSingletonContext<T1> ToProvider( boost::function<T2* (T3, T4)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5>
      NameSingletonContext<T1> ToProvider( boost::function<T2* (T3, T4, T5)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6>
      NameSingletonContext<T1> ToProvider( boost::function<T2* (T3, T4, T5, T6)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6, class T7>
      NameSingletonContext<T1> ToProvider( boost::function<T2* (T3, T4, T5, T6, T7)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container),
            boost::bind(&IContainer::Inject<T7>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2>
      NameSingletonContext<T1> ToProvider( boost::function<boost::shared_ptr<T2> ()> provider )
      {
         mContext->SetProvider(provider);

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3>
      NameSingletonContext<T1> ToProvider( boost::function<boost::shared_ptr<T2> (T3)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4>
      NameSingletonContext<T1> ToProvider( boost::function<boost::shared_ptr<T2> (T3, T4)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5>
      NameSingletonContext<T1> ToProvider( boost::function<boost::shared_ptr<T2> (T3, T4, T5)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6>
      NameSingletonContext<T1> ToProvider( boost::function<boost::shared_ptr<T2> (T3, T4, T5, T6)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6, class T7>
      NameSingletonContext<T1> ToProvider( boost::function<boost::shared_ptr<T2> (T3, T4, T5, T6, T7)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container),
            boost::bind(&IContainer::Inject<T7>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2>
      NameContext<T1> ToProvider( boost::function<T2 (IContainerPtr)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3>
      NameContext<T1> ToProvider( boost::function<T2 (IContainerPtr, T3)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4>
      NameContext<T1> ToProvider( boost::function<T2 (IContainerPtr, T3, T4)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5>
      NameContext<T1> ToProvider( boost::function<T2 (IContainerPtr, T3, T4, T5)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6>
      NameContext<T1> ToProvider( boost::function<T2 (IContainerPtr, T3, T4, T5, T6)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6, class T7>
      NameContext<T1> ToProvider( boost::function<T2 (IContainerPtr, T3, T4, T5, T6, T7)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container),
            boost::bind(&IContainer::Inject<T7>, container)));

         return NameContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2>
      NameSingletonContext<T1> ToProvider( boost::function<T2* (IContainerPtr)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3>
      NameSingletonContext<T1> ToProvider( boost::function<T2* (IContainerPtr, T3)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4>
      NameSingletonContext<T1> ToProvider( boost::function<T2* (IContainerPtr, T3, T4)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5>
      NameSingletonContext<T1> ToProvider( boost::function<T2* (IContainerPtr, T3, T4, T5)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6>
      NameSingletonContext<T1> ToProvider( boost::function<T2* (IContainerPtr, T3, T4, T5, T6)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6, class T7>
      NameSingletonContext<T1> ToProvider( boost::function<T2* (IContainerPtr, T3, T4, T5, T6, T7)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container),
            boost::bind(&IContainer::Inject<T7>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2>
      NameSingletonContext<T1> ToProvider( boost::function<boost::shared_ptr<T2> (IContainerPtr)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3>
      NameSingletonContext<T1> ToProvider( boost::function<boost::shared_ptr<T2> (IContainerPtr, T3)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4>
      NameSingletonContext<T1> ToProvider( boost::function<boost::shared_ptr<T2> (IContainerPtr, T3, T4)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5>
      NameSingletonContext<T1> ToProvider( boost::function<boost::shared_ptr<T2> (IContainerPtr, T3, T4, T5)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6>
      NameSingletonContext<T1> ToProvider( boost::function<boost::shared_ptr<T2> (IContainerPtr, T3, T4, T5, T6)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container)));

         return NameSingletonContext<T1>(mContext);
      }

      //!
      //! Binds the provider.
      //!
      //! @param provider The provider.
      //!
      template<class T2, class T3, class T4, class T5, class T6, class T7>
      NameSingletonContext<T1> ToProvider( boost::function<boost::shared_ptr<T2> (IContainerPtr, T3, T4, T5, T6, T7)> provider )
      {
         IContainerPtr container = mContext->GetContainer();

         mContext->SetProvider(boost::bind(provider, container,
            boost::bind(&IContainer::Inject<T3>, container),
            boost::bind(&IContainer::Inject<T4>, container),
            boost::bind(&IContainer::Inject<T5>, container),
            boost::bind(&IContainer::Inject<T6>, container),
            boost::bind(&IContainer::Inject<T7>, container)));

         return NameSingletonContext<T1>(mContext);
      }

   private :
      boost::shared_ptr<BindContext<T1> > mContext;
   };
}

#endif   // IOCPP_CONFIG_PROVIDERCONTEXT_H
